home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / cron / cron.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  8.6 KB  |  476 lines

  1. /* 
  2.  * cron.c --
  3.  *
  4.  *    Cron daemon.  Reads /hosts/{hostname}/crontab.  Wakes
  5.  *      up periodically to run the commands.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/daemons/cron/RCS/cron.c,v 1.5 90/02/16 12:54:50 douglis Exp Locker: rab $";
  19. #endif /* not lint */
  20.  
  21.  
  22. #include <sys/types.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include <signal.h>
  27. #include <sys/time.h>
  28. #include <sys/stat.h>
  29. #include <sys/wait.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/file.h>
  32. #include <pwd.h>
  33. #include <fcntl.h>
  34.  
  35. #define    LISTS    (2*BUFSIZ)
  36. #define    MAXLIN    BUFSIZ
  37.  
  38. #ifndef CRONTAB
  39. #define CRONTAB "/sprite/lib/cron/crontab"
  40. #endif
  41.  
  42. #ifndef CRONTABLOC
  43. #define CRONTABLOC  "/usr/lib/crontab.local"
  44. #endif
  45.  
  46. #define    EXACT    100
  47. #define    ANY    101
  48. #define    LIST    102
  49. #define    RANGE    103
  50. #define    EOS    104
  51.  
  52. static char    crontab[]    = CRONTAB;
  53. static char    loc_crontab[256]   = CRONTABLOC;
  54. static time_t    itime;
  55. static struct    tm *loct;
  56. extern struct    tm *localtime();
  57. static int    flag;
  58. static char    *list;
  59. static char    *listend;
  60. static unsigned listsize;
  61.  
  62. static FILE    *debug;
  63. #define dprintf if (debug) fprintf
  64.  
  65. static char *cmp();
  66. static void slp();
  67. static void ex();
  68. static void init();
  69. static void append();
  70. static void reapchild();
  71. static void untty();
  72. static int number();
  73. static void Fs_GetPrivateName();
  74.  
  75. void
  76. main(argc, argv)
  77.     int argc;
  78.     char **argv;
  79. {
  80.     register char *cp;
  81.     char *cmp();
  82.     time_t filetime = 0;
  83.     time_t lfiletime = 0;
  84.     char c;
  85.     extern char *optarg;
  86.     extern int errno;
  87.  
  88.      /*
  89.       * Check command line arguments
  90.       */
  91.      c = getopt(argc, argv, "d:");
  92.      if (c == 'd') {
  93.      if ((debug = fopen(optarg, "w")) == NULL) {
  94.          fprintf(stderr, "Can't open %s: %s\n", optarg, strerror(errno));
  95.          exit(1);
  96.      }   
  97.      fcntl(fileno(debug), F_SETFL, FAPPEND);
  98.      }
  99.     /*
  100.      * Detach from parent.
  101.      */
  102.      if (!debug && fork()) {
  103.      exit(0);
  104.      }
  105.  
  106.      chdir("/");
  107.      freopen("/", "r", stdout);
  108.      freopen("/", "r", stderr);
  109.      untty();
  110.  
  111.      /*
  112.       * Ignore signals
  113.       */
  114.      signal(SIGHUP, SIG_IGN);
  115.      signal(SIGINT, SIG_IGN);
  116. #ifndef sprite
  117.      signal(SIGQUIT, SIG_IGN);
  118. #endif
  119.      signal(SIGCHLD, reapchild);
  120.      time(&itime);
  121.      itime -= localtime(&itime)->tm_sec;
  122.  
  123.      Fs_GetPrivateName("crontab", loc_crontab);
  124.  
  125.      for (;; itime+=60, slp()) {
  126.      struct stat cstat, lcstat;
  127.      int newcron, newloc;
  128.  
  129.      newcron = 0;
  130.      if (stat(crontab, &cstat) < 0) {
  131.          cstat.st_mtime = 1;
  132.      }   
  133.      if (cstat.st_mtime != filetime) {
  134.          filetime = cstat.st_mtime;
  135.          newcron++;
  136.      }
  137.      newloc  = 0;
  138.      if (stat(loc_crontab, &lcstat) < 0) {
  139.          lcstat.st_mtime = 1;
  140.      }
  141.      if (lcstat.st_mtime != lfiletime) {
  142.          lfiletime = lcstat.st_mtime;
  143.          newloc++;
  144.      }
  145.      if (newcron || newloc) {
  146.          dprintf(debug, "%x: reading crontab files\n", getpid()),
  147.              fflush(debug);
  148.          init();
  149.          append(crontab);
  150.          append(loc_crontab);
  151.          *listend++ = EOS;
  152.          *listend++ = EOS;
  153.      }
  154.      loct = localtime(&itime);
  155.      loct->tm_mon++;         /* 1-12 for month */
  156.      if (loct->tm_wday == 0) {
  157.          loct->tm_wday = 7;    /* sunday is 7, not 0 */
  158.      }
  159.      for(cp = list; *cp != EOS;) {
  160.          flag = 0;
  161.          cp = cmp(cp, loct->tm_min);
  162.          cp = cmp(cp, loct->tm_hour);
  163.          cp = cmp(cp, loct->tm_mday);
  164.          cp = cmp(cp, loct->tm_mon);
  165.          cp = cmp(cp, loct->tm_wday);
  166.          if(flag == 0) {
  167.          ex(cp);
  168.          }   
  169.          while(*cp++ != 0) {
  170.          ;
  171.          }
  172.      }
  173.      }   
  174. }
  175.  
  176. static char *
  177. cmp(p, v)
  178.     char *p;
  179. {
  180.     register char *cp;
  181.  
  182.     cp = p;
  183.     switch(*cp++) {
  184.  
  185.     case EXACT:
  186.     if (*cp++ != v) {
  187.         flag++;
  188.     }
  189.     return cp;
  190.  
  191.     case ANY:
  192.     return cp;
  193.  
  194.     case LIST:
  195.     while(*cp != LIST) {
  196.         if(*cp++ == v) {
  197.         while(*cp++ != LIST) {
  198.             ;
  199.         }
  200.         return cp;
  201.         }
  202.     }
  203.     flag++;
  204.     return cp+1;
  205.  
  206.     case RANGE:
  207.     if(*cp > v || cp[1] < v) {
  208.         flag++;
  209.     }
  210.     return cp+2;
  211.     }
  212.     if(cp[-1] != v) {
  213.     flag++;
  214.     }
  215.     return cp;
  216. }
  217.  
  218. static void
  219. slp()
  220. {
  221.     register i;
  222.     time_t t;
  223.  
  224.     time(&t);
  225.     i = itime - t;
  226.     if(i < -60 * 60 || i > 60 * 60) {
  227.     itime = t;
  228.     i = 60 - localtime(&itime)->tm_sec;
  229.     itime += i;
  230.     }
  231.     if(i > 0) {
  232.     sleep(i);
  233.     }
  234.     return;
  235. }
  236.  
  237. static void
  238. ex(s)
  239.     char *s;
  240. {
  241.     int st;
  242.     register struct passwd *pwd;
  243.     char user[BUFSIZ];
  244.     char *c = user;
  245.     int pid;
  246.  
  247.     if (fork()) {
  248.     return;
  249.     }
  250.  
  251.     pid = getpid();
  252.     while(*s != ' ' && *s != '\t') {
  253.     *c++ = *s++;
  254.     }
  255.     *c = '\0';
  256.     s++;
  257.     if ((pwd = getpwnam(user)) == NULL) {
  258.     dprintf(debug, "%x: cannot find %s\n", pid, user),
  259.         fflush(debug);
  260.         exit(1);
  261.     }   
  262.     (void) setgid(pwd->pw_gid);
  263.     initgroups(pwd->pw_name, pwd->pw_gid);
  264.     (void) setuid(pwd->pw_uid);
  265.     freopen("/", "r", stdin);
  266.     dprintf(debug, "%x: executing %s", pid, s), fflush (debug);
  267.     execl("/bin/sh", "sh", "-c", s, 0);
  268.     dprintf(debug, "%x: cannot execute sh\n", pid), fflush (debug);
  269.     exit(0);
  270. }
  271.  
  272. static void
  273. init()
  274. {
  275.     /*
  276.      * Don't free in case was longer than LISTS.  Trades off
  277.      * the rare case of crontab shrinking vs. the common case of
  278.      * extra realloc's needed in append() for a large crontab.
  279.      */
  280.     if (list == 0) {
  281.     list = malloc(LISTS);
  282.     listsize = LISTS;
  283.     }
  284.     listend = list;
  285.     return;
  286. }
  287.  
  288. static void
  289. append(fn)
  290.     char *fn;
  291. {
  292.     register i, c;
  293.     register char *cp;
  294.     register char *ocp;
  295.     register int n;
  296.  
  297.     if (freopen(fn, "r", stdin) == NULL) {
  298.     return;
  299.     }
  300.     cp = listend;
  301. loop:
  302.     if(cp > list+listsize-MAXLIN) {
  303.     int length = cp - list;
  304.  
  305.     listsize += LISTS;
  306.     list = realloc(list, listsize);
  307.     cp = list + length;
  308.     }
  309.     ocp = cp;
  310.     for(i=0;; i++) {
  311.     do {
  312.         c = getchar();
  313.     } while(c == ' ' || c == '\t');
  314.     if(c == EOF || c == '\n') {
  315.         goto ignore;
  316.     }
  317.     if(i == 5) {
  318.         break;
  319.     }
  320.     if(c == '*') {
  321.         *cp++ = ANY;
  322.         continue;
  323.     }
  324.     if ((n = number(c)) < 0) {
  325.         goto ignore;
  326.     }
  327.     c = getchar();
  328.     if(c == ',') {
  329.         goto mlist;
  330.     }
  331.     if(c == '-') {
  332.         goto mrange;
  333.     }
  334.     if(c != '\t' && c != ' ') {
  335.         goto ignore;
  336.     }
  337.     *cp++ = EXACT;
  338.     *cp++ = n;
  339.     continue;
  340.  
  341.     mlist:
  342.     *cp++ = LIST;
  343.     *cp++ = n;
  344.     do {
  345.         if ((n = number(getchar())) < 0) {
  346.         goto ignore;
  347.         }
  348.         *cp++ = n;
  349.         c = getchar();
  350.     } while (c==',');
  351.     if(c != '\t' && c != ' ') {
  352.         goto ignore;
  353.     }
  354.     *cp++ = LIST;
  355.     continue;
  356.  
  357.     mrange:
  358.     *cp++ = RANGE;
  359.     *cp++ = n;
  360.     if ((n = number(getchar())) < 0) {
  361.             goto ignore;
  362.     }
  363.     c = getchar();
  364.     if(c != '\t' && c != ' ') {
  365.         goto ignore;
  366.     }
  367.     *cp++ = n;
  368.     }
  369.     while(c != '\n') {
  370.     if(c == EOF) {
  371.         goto ignore;
  372.     }
  373.     if(c == '%') {
  374.         c = '\n';
  375.     }
  376.     *cp++ = c;
  377.     c = getchar();
  378.     }
  379.     *cp++ = '\n';
  380.     *cp++ = 0;
  381.     goto loop;
  382.  
  383. ignore:
  384.     cp = ocp;
  385.     while(c != '\n') {
  386.     if(c == EOF) {
  387.         fclose(stdin);
  388.         listend = cp;
  389.         return;
  390.     }
  391.     c = getchar();
  392.     }
  393.     goto loop;
  394. }
  395.  
  396. static int
  397. number(c)
  398.     register c;
  399. {
  400.     register n = 0;
  401.  
  402.     while (isdigit(c)) {
  403.     n = n*10 + c - '0';
  404.     c = getchar();
  405.     }
  406.     ungetc(c, stdin);
  407.     if (n>=100) {
  408.     return -1;
  409.     }
  410.     return n;
  411. }
  412.  
  413. static void
  414. reapchild()
  415. {
  416.     union wait status;
  417.     int pid;
  418.  
  419.     while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
  420.     dprintf(debug, "%x: child exits with signal %d status %d\n",
  421.         pid, status.w_termsig, status.w_retcode),
  422.         fflush (debug);
  423.     }
  424.     return;
  425. }
  426.  
  427. static void
  428. untty()
  429. {
  430.     int i;
  431.  
  432.     i = open("/dev/tty", O_RDWR);
  433.     if (i >= 0) {
  434.     ioctl(i, TIOCNOTTY, (char *)0);
  435.     (void) close(i);
  436.     }
  437.     return;
  438. }
  439.  
  440.  
  441. /*
  442.  *----------------------------------------------------------------------
  443.  *
  444.  * Fs_GetPrivateName --
  445.  *
  446.  *      Fill a buffer with the path name of a file private to the local
  447.  *      machine. The file is located in /hosts/<hostname>/<file>
  448.  *
  449.  * Results:
  450.  *      The path of the file.
  451.  *
  452.  * Side Effects:
  453.  *      The passed buffer is overwritten.
  454.  *
  455.  *----------------------------------------------------------------------
  456.  */
  457. static void
  458. Fs_GetPrivateName (fileName, bufPtr)
  459.     char                *fileName;      /* Short name of private file */
  460.     char                *bufPtr;        /* Pointer to buffer for storage */
  461. {
  462.     static int          initialized = 0;
  463.     static char         hostname[64];   /* Name of local host */
  464.  
  465. #define PRIVATE_DIR     "/hosts"
  466.  
  467.     if (!initialized) {
  468.         gethostname (hostname, sizeof(hostname));
  469.     hostname[sizeof(hostname)-1] = 0;
  470.         initialized = 1;
  471.     }
  472.  
  473.     sprintf (bufPtr, "%s/%s/%s", PRIVATE_DIR, hostname, fileName);
  474.     return;
  475. }
  476.